#include "includes.h"

int park_prober_scan()
{
	struct list_head *pstPosArea, *pstPosProber;
	PS_AREA pstArea;
	PS_PROBER pstProber;


	list_for_each(pstPosArea, &stPark.area_list)
	{
		pstArea = list_entry(pstPosArea, S_AREA, area_sys_list);
		list_for_each(pstPosProber, &pstArea->prober_list)
		{
			pstProber = list_entry(pstPosProber, S_PROBER, prober_list);
			if (pstProber->stat == PROBER_STAT_ONLINE)
				return -1;
		}
	}
	return 0;
}

void park_prober_modify_stat()
{
	struct list_head *pstPosArea, *pstPosProber;
	PS_AREA pstArea;
	PS_PROBER pstProber;

	list_for_each(pstPosArea, &stPark.area_list)
	{
		pstArea = list_entry(pstPosArea, S_AREA, area_sys_list);
		list_for_each(pstPosProber, &pstArea->prober_list)
		{
			pstProber = list_entry(pstPosProber, S_PROBER, prober_list);
			if (pstProber->stat == PROBER_STAT_ONLINE)
				pstProber->stat = PROBER_STAT_OFFLINE;
		}
	}
	return;
}

int park_prober_is_online(PS_PROBER pstProber)
{
	int ret;
	if (pstProber == NULL)
	{
		DBG("pstProber is NULL!!\n");
		return -1;
	}
	
	bzero(&stPark.prober_connect_fd, sizeof(NET_SOCKET_T));
	stPark.prober_connect_fd.s_type = NET_ST_CLIENT;
	stPark.prober_connect_fd.in_event = NULL;

	ret = net_socket_init(&stPark.stNet, &stPark.prober_connect_fd, pstProber->ip_addr, PARK_PROBER_SEARCH_PORT);
	if (ret != 0)
	{
		//net_socket_destroy(&stPark.prober_connect_fd);
		return -1;
	}
	else
	{
		net_socket_destroy(&stPark.prober_connect_fd);
		return 0;
	}
}

int park_prober_send_config_packet(PS_PROBER pstProber)
{
	//int i;
	int ret;
	//int cnt = 0;
	char *buff;
	struct list_head *pstPos;
	PS_SENSOR pst, pstPosSensor;
	PS_PARK_PROBER_HEAD pstProber_head;
	
	if (pstProber == NULL)
	{
		DBG("pstProber is NULL!!\n");
		return -1;
	}

	bzero(&stPark.prober_connect_fd, sizeof(NET_SOCKET_T));
	stPark.prober_connect_fd.s_type = NET_ST_CLIENT;
	stPark.prober_connect_fd.in_event = NULL;
	//printf("pstProber->ip_addr %s\n", pstProber->ip_addr);
	ret = net_socket_init(&stPark.stNet, &stPark.prober_connect_fd, pstProber->ip_addr, PARK_PROBER_SEARCH_PORT);
	if (ret != 0)
	{
		DBG("connect the addr %s port %d prober failed\n", pstProber->ip_addr, PARK_PROBER_SEARCH_PORT);
		//pstProber->stat = PARK_PROBER_OFFLINE;
		stPark.prober_num_offline++;
		return -1 ;
	}

	buff = Malloc(pstProber->sensor_cnt*sizeof(S_SENSOR)+sizeof(S_PARK_PROBER_HEAD));
	pstProber_head = (PS_PARK_PROBER_HEAD)buff;

	SOCKET_GetLocalIp("eth0", pstProber_head->agent_addr);
	pstProber_head->probr_id = pstProber->prober_id;
	pstProber_head->config_id = stPark.cur_config_id;
	
	pst = (PS_SENSOR)pstProber_head->sensor;
	list_for_each(pstPos, &pstProber->sensor_list)
	{
		pstPosSensor = list_entry(pstPos, S_SENSOR, sensor_list);
		memcpy(pst, pstPosSensor, sizeof(S_SENSOR));
		pst++;
	}
	/*
	for (i=0; i<PROBER_IO_NUM; i++)
	{
		list_for_each_a(pstPos, &pstProber->pstSensor_a[i]->sensor_list)
		{
			pstPosSensor = list_entry(pstPos, S_SENSOR, sensor_list);
			memcpy(pst, pstPosSensor, sizeof(S_SENSOR));
			pst++;
			if (++cnt > PARK_PROBER_MAX_SENSOR)
			{
				i = PROBER_IO_NUM;
				break;
			}
		}
	}
	*/
	//printf("2121\n");
	pstProber_head->sensor_num = pstProber->sensor_cnt;
	ret = net_socket_send_data(&stPark.prober_connect_fd, buff, pstProber->sensor_cnt*sizeof(S_SENSOR)+sizeof(S_PARK_PROBER_HEAD));
	if (ret != 0)
	{
		//pstProber->stat = PARK_PROBER_OFFLINE;
		stPark.prober_num_offline++;
		free(buff);
		net_socket_destroy(&stPark.prober_connect_fd);
		return -1;
	}
	
	//printf("1313\n");
	//pstProber->stat = PARK_PROBER_ONLINE;
	stPark.prober_num_online++;
	free(buff);
	net_socket_destroy(&stPark.prober_connect_fd);
	return 0;
}


void park_prober_send_req()
{
	struct list_head *pstPosArea, *pstPosProber;
	PS_AREA pstArea;
	PS_PROBER pstProber;
	//int cnt = 0;
	
	stPark.prober_num_offline = stPark.prober_num_online = 0;
	list_for_each(pstPosArea, &stPark.area_list)
	{
		pstArea = list_entry(pstPosArea, S_AREA, area_sys_list);
		list_for_each(pstPosProber, &pstArea->prober_list)
		{
			//cnt++;
			pstProber = list_entry(pstPosProber, S_PROBER, prober_list);
			if (park_prober_send_config_packet(pstProber) != 0)
				pstProber->stat = PARK_PROBER_OFFLINE;
			else
				pstProber->stat = PARK_PROBER_ONLINE;
		}
	}
	DBG("prober online (%d) offline (%d) !!!\n", stPark.prober_num_online, stPark.prober_num_offline);
	return;
}

static PS_PROBER park_prober_match_addr(char *addr)
{
	struct list_head *pstPosArea, *pstPosProber;
	PS_AREA pstArea;
	PS_PROBER pstProber;
	
	list_for_each(pstPosArea, &stPark.area_list)
	{
		pstArea = list_entry(pstPosArea, S_AREA, area_sys_list);
		list_for_each(pstPosProber, &pstArea->prober_list)
		{
			pstProber = list_entry(pstPosProber, S_PROBER, prober_list);
			if (strncmp(pstProber->ip_addr, addr, 20) == 0)
				return pstProber;
		}
	}
	
	return NULL;
}


static void park_prober_packet_deal(struct _NET_SOCKET_T *pstNetobject)
{
	PS_SENSOR_TRAP_HEAD pstSensor_trap_head;
	PS_PROBER pstSearch_prober;
	PS_SENSOR_TRAP pstTrap_sensor;
	PS_SENSOR pstSearch_sensor;
	int i;

	if (park_get_stat()!=PARK_STAT_RUN && park_get_stat()!=PARK_STAT_IDLE && park_get_stat()!=PARK_STAT_RUN_INIT)
	{
		DBG("park_get_stat() != PARK_STAT_RUN || PARK_STAT_IDLE || PARK_STAT_RUN_INIT!!\n");
		return;
	}
	
	pstSensor_trap_head = (PS_SENSOR_TRAP_HEAD)pstNetobject->buf;

	
	
	switch(pstSensor_trap_head->trap_type)
	{
		case SENSOR_TRAP_TYPE_DATAREQ:			
			if (pstSensor_trap_head->config_id != stPark.cur_config_id)
			{
				DBG("config id error!!\n");
				return;
			}
			
			pstSearch_prober = (PS_PROBER)hash_search_list(stPark.pstHash ,&pstSensor_trap_head->prober_id);
			if (pstSearch_prober->dev_type != PARK_DEV_TYPE_PROBER)
			{
				DBG("hash prober dev type error!! type %d\n", pstSearch_prober->dev_type);
				return;
			}
			pstTrap_sensor = (PS_SENSOR_TRAP)pstSensor_trap_head->sensor;
			for (i=0; i<pstSensor_trap_head->sensor_num; i++)
			{
				pstSearch_sensor = (PS_SENSOR)hash_search_list(stPark.pstHash ,&pstTrap_sensor->sensor_id);
				if (pstSearch_sensor->dev_type != PARK_DEV_TYPE_SENSOR)
				{
					DBG("hash sensor dev type error!!\n");
				}
				else
				{ 
					pstSearch_sensor->stat = pstTrap_sensor->sensor_stat;
				}
				pstTrap_sensor++;
			}
			pstSearch_prober->updata_time = time(NULL);
			pstSearch_prober->stat = PROBER_STAT_UPDATA;
			break;
		case SENSOR_TRAP_TYPE_STATCHANGE:			
			if (pstSensor_trap_head->config_id != stPark.cur_config_id)
			{
				DBG("config id error!!\n");
				return;
			}
			
			pstSearch_prober = (PS_PROBER)hash_search_list(stPark.pstHash ,&pstSensor_trap_head->prober_id);
			if (pstSearch_prober->dev_type != PARK_DEV_TYPE_PROBER)
			{
				DBG("hash prober dev type error!!\n");
				return;
			}
			if (pstSearch_prober->stat != PROBER_STAT_UPDATA)
			{
				if (pstSearch_prober->stat!=PROBER_STAT_REQ)
					pstSearch_prober->stat = PROBER_STAT_REQ;
			}
			else
			{
				pstTrap_sensor = (PS_SENSOR_TRAP)pstSensor_trap_head->sensor;
				for (i=0; i<pstSensor_trap_head->sensor_num; i++)
				{
					pstSearch_sensor = (PS_SENSOR)hash_search_list(stPark.pstHash ,&pstTrap_sensor->sensor_id);
					if (pstSearch_sensor->dev_type != PARK_DEV_TYPE_SENSOR)
					{
						DBG("hash sensor dev type error!!\n");
					}
					else
					{ 
						pstSearch_sensor->stat = pstTrap_sensor->sensor_stat;
					}
					pstTrap_sensor++;
				}
				pstSearch_prober->updata_time = time(NULL);
			}
			break;
		case SENSOR_TRAP_TYPE_REQ:
			pstSearch_prober = park_prober_match_addr(pstSensor_trap_head->prober_addr);
			if (pstSearch_prober == NULL)
			{
				DBG("can not find the addr %s prober!!\n", pstSensor_trap_head->prober_addr);
				return;
			}
			pstSearch_prober->stat = PROBER_STAT_REQ;
			park_set_stat(PARK_STAT_RUN);
			Sem_post(&stPark.park_sem);
			break;
	}
}


void park_prober_init()
{
	int ret;
	memset(&stPark.prober_listen_fd, 0, sizeof(NET_SOCKET_T));
	stPark.prober_listen_fd.s_type = NET_ST_SERVER;
	stPark.prober_listen_fd.in_event = park_prober_packet_deal;
	ret = net_socket_init(&stPark.stNet, &stPark.prober_listen_fd, NULL, PARK_PROBER_LISTEN_PORT);
	if (ret != 0)
	{
		ERR_SYS("net_socket_init error!");
	}
	return;
}

void park_prober_destroy()
{
	net_socket_destroy(&stPark.prober_listen_fd);
}

